/*
 * @Author: xiaosihan
 * @Date: 2023-02-06 15:22:57
 * @Last Modified by: xiaosihan
 * @Last Modified time: 2023-05-07 20:28:47
 */
import hashHistory from '@hashHistory';
import { AmbientLight, BoxGeometry, DirectionalLight, DoubleSide, Euler, Mesh, MeshLambertMaterial, MeshPhongMaterial, PointLight, Vector3, WebGLRenderer } from 'three';
import ThreeBase from 'three-base';
import KeyFrameAnimation from 'three-base/KeyFrameAnimation';
import PlaneModal1 from 'three-base/PlaneModal1';
import SpriteModal1 from 'three-base/SpriteModal1';
import Text3D from 'three-base/Text3D';
import threeUtils from 'three-base/threeUtils';
import Transition from 'three-base/Transition';
import { degToRad } from 'three/src/math/MathUtils';
import GLTF from './component3d/GLTF/GLTF';
import road1PNG from './img/road1.png';

import ExtrudeMesh from 'three-base/ExtrudeMesh';
import Fire from 'three-base/Fire/Fire';
import PlaneWithHtml from 'three-base/PlaneWithHtml';
import Sky from 'three-base/Sky/Sky';
import SpriteText2 from 'three-base/SpriteText2';
import SpriteWithHtml from 'three-base/SpriteWithHtml';
import threeLoader from 'three-base/threeLoader';
import uvJPG from './img/uv.jpg';
import InstancedMeshBase from 'three-base/InstancedMeshBase';
import bottleGLB from "./glb/bottle.glb?url";


/**
 *
 *
 * @class HomeRender
 * @extends {ThreeBase}
 */
class HomeRender extends ThreeBase {
  constructor() {
    super();
  }

  // 环境光
  ambientLight = (() => {
    const ambientLight = new AmbientLight('#fff', 1.5);
    this.scene.add(ambientLight);
    return ambientLight;
  })();

  //点光源
  pointLight = (() => {
    const pointLight = new PointLight('#fff', 1.5);
    pointLight.position.set(50, 40, 50);
    pointLight.shadow.bias = -0.001;
    this.scene.add(pointLight);
    return pointLight;
  })();

  // 方向光
  directionalLight = (() => {
    const directionalLight = new DirectionalLight('#fff', 1.5);
    directionalLight.position.set(-10, 10, 5);
    directionalLight.target.position.set(0, 0, 0);
    directionalLight.castShadow = true;
    directionalLight.shadow.bias = -0.001;
    directionalLight.shadow.mapSize.set(1024, 1024);
    this.scene.add(directionalLight);
    return directionalLight;
  })();

  init() {
    super.init();

    // 开发模式时还原记录的位置
    if (threeUtils.isDev && localStorage.lookAt) {
      this.resetLookAt({
        ...JSON.parse(localStorage.lookAt),
      });
    }

    // 开发模式时记录当前的位置
    if (threeUtils.isDev) {
      this.controls.addEventListener('change', () => {
        localStorage.lookAt = JSON.stringify(this.getLookAt());
      });
    }

    if (threeUtils.isProd || (threeUtils.isDev && !localStorage.lookAt)) {
      this.resetLookAt({
        center: new Vector3(0, 0, 0),
        position: new Vector3(-7.049, 27.469, 59.276),
      });
    }
  }

  //火焰
  fire = (() => {
    const fire = new Fire();
    fire.position.set(10, 0, 10);
    this.scene.add(fire);
    return fire;
  })();

  // 发光测试
  glow_test = (() => {
    const glow_test = new Text3D('辉光测试');
    glow_test.scale.set(2, 2, 2);
    glow_test.position.set(-10, 8, 0);

    glow_test.userData = {
      glow_enable: true, //启用发光
      glow_color: '#04fa12', //发光颜色
      glow_width: 50, //发光厚度(像素)
    };

    this.scene.add(glow_test);
    return glow_test;
  })();

  // 描边测试
  stroke_test = (() => {
    const glow_test = new Text3D('描边测试');
    glow_test.scale.set(2, 2, 2);
    glow_test.position.set(-10, 5, 0);

    glow_test.userData = {
      stroke_enable: true, //启用描边
      stroke_color: '#04fa12', //描边颜色
      stroke_width: 4, //描边厚度(像素)
    };

    this.scene.add(glow_test);
    return glow_test;
  })();

  //一个立方体
  box = (() => {
    const geometry = new BoxGeometry(5, 5, 5);
    const matearil = new MeshLambertMaterial({
      color: '#ffffff',
      map: threeLoader.getTexture(uvJPG),
    });
    const mesh = new Mesh(geometry, matearil);

    const transition = new Transition({ rotationY: 0, y: 0 });

    // 动画对象播放回调
    transition.onChange(({ rotationY, y }) => {
      mesh.rotation.y = rotationY;
      mesh.position.setY(y);
      this.needRender = true;
    });

    mesh.position.set(-10, 0, 0);
    mesh.userData = {
      cursor: 'pointer',
      enableEvent: true,
      glow_enable: false, //启用发光
      glow_color: '#04fa12', //发光颜色
      glow_width: 40, //发光厚度(像素)
    };

    // 点击设置动画对象的值
    mesh.addEventListener('click', (e) => {});

    mesh.addEventListener('dbclick', (e) => {
      console.log('dbclick');
    });

    mesh.addEventListener('leftclick', (e) => {
      transition.set({
        rotationY: Math.random() * 5,
        y: Math.random() * 5,
      });
    });
    mesh.addEventListener('rightclick', (e) => {
      hashHistory.push('/home2');
    });
    // 鼠标移入就发光
    mesh.addEventListener('mouseenter', (e) => {
      mesh.userData.glow_enable = true; //启用发光
    });

    // 鼠标离开就不发光
    mesh.addEventListener('mouseleave', (e) => {
      mesh.userData.glow_enable = false; //启用发光
    });
    mesh.addEventListener('mousemove', (e) => {});
    mesh.addEventListener('mousedown', (e) => {});
    mesh.addEventListener('mouseup', (e) => {});

    // 使用键盘修改模型的位置
    // keyContorls.addEventListener("change", e => {
    //     mesh.position.add(e.direction);
    //     console.log(mesh.position.toArray().join(" ,"));
    // });

    this.scene.add(mesh);
    return mesh;
  })();

  //天空
  sky = (() => {
    const sky = new Sky();
    this.scene.add(sky);
    return sky;
  })();

  // 加载 gltf
  gltf = (() => {
    const gltf = new GLTF();
    gltf.scale.set(10, 10, 10);
    gltf.position.set(20, 0, 0);
    this.scene.add(gltf);
    return gltf;
  })();

  //关键帧动画对象测试
  keyFrameAnimation = (() => {
    // 创建一个立方体
    const geometry = new BoxGeometry(5, 1, 5);
    const matearil = new MeshLambertMaterial({ color: '#f0f', wireframe: true });
    const mesh = new Mesh(geometry, matearil);

    //创建关键帧动画对象
    const keyFrameAnimation = new KeyFrameAnimation({
      object3d: mesh,
      keyframes: [
        { position: new Vector3(0, 0, 0), scale: new Vector3(1, 1, 1), rotation: new Euler(0, 0, 0), timeTemp: 0 },
        { position: new Vector3(0, 5, 1), scale: new Vector3(1, 1, 1), rotation: new Euler(0, degToRad(0), 0), timeTemp: 5000 },
        { position: new Vector3(0, 5, 5), scale: new Vector3(1, 1, 1), rotation: new Euler(0, degToRad(0), 0), timeTemp: 10000 },
      ],
    });

    // 当前
    keyFrameAnimation.addEventListener('update', () => {
      this.needRender = true;
    });

    this.scene.add(keyFrameAnimation);

    return keyFrameAnimation;
  })();

  //3D组件提示窗
  spriteModal1 = (() => {
    const spriteModal1 = new SpriteModal1();
    // 更新文本
    spriteModal1.updata({
      size: 10,
      title: 'SpriteModal1',
      titleColor: '#ffffff',
      texts: [{ text: '3D组件提示窗 SpriteModal1' }, { text: '支持鼠标事件,自动换行,文字颜色,文字大小', color: '#ffff00' }, { text: '使用\\n换行', color: '#00ffff' }],
    });
    spriteModal1.userData = { cursor: 'pointer', enableEvent: true };
    spriteModal1.addEventListener('leftclick', (e) => {});
    spriteModal1.position.set(-20, 0, 0);
    this.scene.add(spriteModal1);
    return spriteModal1;
  })();

  //3D平面组件提示窗
  planeModal1 = (() => {
    const planeModal1 = new PlaneModal1();
    // 更新文本
    planeModal1.updata({
      size: 10,
      title: 'PlaneModal1',
      titleColor: '#ffffff',
      texts: [{ text: '3D平面组件弹窗 PlaneModal1' }, { text: '支持鼠标事件,自动换行,文字颜色,文字大小', color: '#ffff00' }, { text: '使用\\n换行', color: '#00ffff' }],
    });
    planeModal1.userData = { cursor: 'pointer', enableEvent: true };
    planeModal1.addEventListener('leftclick', (e) => {});
    planeModal1.position.set(-30, 0, 0);
    this.scene.add(planeModal1);
    return planeModal1;
  })();

  // 3D文字
  text3D = (() => {
    const text3D = new Text3D('new Text3D\n3d文字组件');
    text3D.position.set(6, 2, 0);
    this.scene.add(text3D);
    return text3D;
  })();

  // htlml样式面板
  planeWithHtml = (() => {
    const planeWithHtml = new PlaneWithHtml(`
            <span style="font-family: 黑体;font-size:100px;color:#000;" >PlaneWithHtml</span>
            <br/>
            <span style="font-family: 黑体;font-size:100px;color:#f00;" >htlml文字组件</span>
        `);
    planeWithHtml.position.set(6, 6, 0);
    planeWithHtml.scale.set(0.01, 0.01, 0.01);
    planeWithHtml.rotateX(degToRad(90));

    //three事件
    planeWithHtml.userData = { cursor: 'pointer', enableEvent: true };
    planeWithHtml.addEventListener('leftclick', (e) => {});

    this.scene.add(planeWithHtml);
    return planeWithHtml;
  })();

  // htlml样式面板
  spriteWithHtml = (() => {
    const spriteWithHtml = new SpriteWithHtml();

    spriteWithHtml.position.set(6, 9, 0);

    spriteWithHtml
      .setHtml(
        `
            <span style="font-family: 黑体;font-size:100px;color:#000;" >PlaneWithHtml</span>
            <br/>
            <span style="font-family: 黑体;font-size:100px;color:#f00;" >htlml文字组件</span>
        `
      )
      .then(() => {
        spriteWithHtml.scale.multiplyScalar(0.01);
      });

    this.scene.add(spriteWithHtml);
    return spriteWithHtml;
  })();

  // 挤出公路模型
  extrudeMesh = (() => {
    const material = new MeshPhongMaterial({
      side: DoubleSide,
      map: threeLoader.getTexture(road1PNG),
    });
    const extrudeMesh = new ExtrudeMesh(
      {
        paths: [
          // 挤出路径的点位置    转弯半径   转弯分段数     当前点的缩放            取个名字
          { vector3: [0, 0, -10], radius: 3, segments: 2, scale: { x: 1, y: 1 }, name: '路口1' },
          { vector3: [40, 0, -10], radius: 3, segments: 2, scale: { x: 1, y: 1 }, name: '路口1' },
          { vector3: [40, 0, 10], radius: 3, segments: 2, scale: { x: 1, y: 1 }, name: '路口1' },
          { vector3: [0, 0, 10], radius: 3, segments: 2, scale: { x: 1, y: 1 }, name: '路口1' },
        ], // 自动生成路径的
        shapePath: [
          [-2, 0],
          [2, 0],
        ], // 被拉伸成模型的平面路径
        closed: false, // 是否闭合路径
      },
      material
    );
    this.scene.add(extrudeMesh);
    return extrudeMesh;
  })();

  // 精灵文字样式2
  spriteText2 = (() => {
    const spriteText2 = new SpriteText2('精灵文字2');
    //three事件
    spriteText2.userData = {
      cursor: 'pointer',
      enableEvent: true,
    };
    spriteText2.addEventListener('leftclick', (e) => {
      if (spriteText2.text === '精灵文字2') {
        spriteText2.text = 'SpriteText2';
      } else {
        spriteText2.text = '精灵文字2';
      }
    });

    spriteText2.padding = 1;
    spriteText2.backgroundColor = 'rgba(0,0,0,0.5)';
    spriteText2.borderColor = '#fff000';
    spriteText2.borderWidth = 1;
    spriteText2.borderRadius = 4;
    spriteText2.position.set(0, 15, 0);
    this.scene.add(spriteText2);
    return spriteText2;
  })();

  //加载实例模型的例子,瓷瓶模型
  instancedMeshBase = (() => {
    const instancedMeshBase = new InstancedMeshBase(bottleGLB);
    instancedMeshBase.addEventListener('loaded', () => {
      //设置实例组的长度
      instancedMeshBase.setCount(2);
      // 这个方法可以不用操作矩阵
      instancedMeshBase.setTRS(0, {
        scale: new Vector3(1.2, 1.2, 1.2),
        position: new Vector3(0, 0, 0),
        rotation: new Euler(0, 0, 0),
      });

      instancedMeshBase.setTRS(1, {
        scale: new Vector3(1.5, 1.5, 1.5),
        position: new Vector3(4, 0, 0),
        rotation: new Euler(0, 0, 0),
      });

    });
    this.add(instancedMeshBase);
    return instancedMeshBase;
  })();
}

const homeRenderer = (window.homeRenderer = new HomeRender());

export default homeRenderer;
